﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace FishServe.Build.Common
{
	//Similar class in FishServer.Client
	// Maybe move this into its own project (ie. like a dev utility project)
	/// <summary>
	/// Design by contract utility; used to check object contract adherence by client objects
	/// </summary>
	public static class DBC
	{

		//Not worried about differentiating between pre/post conditions and invariants here

		public static void AssertNotNull(object pObject, string pMessage, params string[] pArguments)
		{
			AssertNotNull(pObject, String.Format(pMessage, pArguments));
		}
		/// <summary>
		/// Assert that the object is not null; any type
		/// </summary>
		/// <param name="pObject"></param>
		/// <param name="pMessage"></param>
		/// <exception cref="DesignByContract.AssertionFailureException">If the assertion condition would be false</exception> 
		public static void AssertNotNull(object pObject, string pMessage)
		{
			Assert(pObject != null, pMessage);
		}

		/// <summary>
		/// Assert that the object is not null; use with string types only
		/// </summary>
		/// <param name="pString"></param>
		/// <param name="pMessage"></param>
		/// <exception cref="DesignByContract.AssertionFailureException">If the assertion condition would be false</exception> 
		public static void AssertNotNullOrEmpty(string pString, string pMessage)
		{
			Assert(pString != null && pString.Trim() != String.Empty, pMessage);
		}

		/// <summary>
		/// Assert that the condition is true
		/// </summary>
		/// <param name="pCondition"></param>
		/// <param name="pMessage"></param>
		/// <exception cref="DesignByContract.AssertionFailureException">If the assertion condition would be false</exception> 
		public static void Assert(bool pCondition, string pMessage)
		{
			if (!pCondition)
				throw new AssertionFailureException(pMessage);
			//Debug.Assert(pCondition, pMessage);
		}

		public static void Assert(bool pCondition, string pMessage, params string[] pArguments)
		{
			Assert(pCondition, String.Format(pMessage, pArguments));
		}

		/// <summary>
		/// Assert that a sub class must implement a certain message
		/// </summary>
		/// <param name="pMessage"></param>
		public static void AssertSubTypeResponsibility(string pMessage)
		{
			throw new NotImplementedException(pMessage);
		}

		/// <summary>
		/// Assert that a sub class must implement a certain message; use this form to supply a never returned
		/// return value in classes that cannot, or should not, be marked abstract
		/// </summary>
		/// <param name="pMessage"></param>
		public static T AssertSubTypeResponsibility<T>(string pMessage)
		{
			throw new NotImplementedException(pMessage);
		}
	}

	/// <summary>
	/// Thrown by the DBC class when an assertion fails
	/// </summary>
	[Serializable]
	public class AssertionFailureException : ApplicationException
	{

		public AssertionFailureException()
			: base()
		{
		}

		public AssertionFailureException(string pMessage)
			: base(pMessage)
		{
		}

		public AssertionFailureException(string pMessage, Exception pException)
			: base(pMessage, pException)
		{
		}
	}
}
